using Unity.Mathematics;

namespace DA.AnimGraph {

    public enum EaseType : byte {
        None = 0,
        Weight,
    }

    // Update的方式固定，通过设置不同参数适应各种情况
    // 提供多个开启方式，根据情况选用
    // 非必要不直接赋值
    public struct AlphaEase {
        public EaseFunctionType easeFunctionType;

        public float remainingTime; // 剩余过渡时间，每帧更新

        //public float time; // 好像没用
        public float duration; // 过渡时间，根据过渡策略含义不同，可以是总时间，也可以是当前到最终的时间（因为不一定从起始值开始）
        public float beginValue; // 起始值
        public float goalValue; // 目标值
        public float timeAlpha; // 时间进度百分比
        // 以上是开启缓动时需要设置的

        public float outputValue; // Update后的计算结果

        /// <returns>返回未用完的时间</returns>
        public float Update(float deltaTime) {
            if (remainingTime > 0) {
                if (remainingTime > deltaTime) {
                    var remainingAlpha = 1 - timeAlpha;
                    timeAlpha += remainingAlpha / remainingTime * deltaTime;
                    remainingTime -= deltaTime;
                    SetAlpha(timeAlpha);
                } else {
                    var overshoot = deltaTime - remainingTime;
                    remainingTime = 0;
                    SetAlpha(1);
                    return overshoot;
                }
            }
            return 0;
        }

        public void SetDuration(float duration) {
            this.duration = duration;
        }

        /// <summary>
        /// 设置初始值
        /// </summary>
        public void SetInitValue(float value) {
            goalValue = value;
            outputValue = value;
        }

        /// <summary>
        /// 权重过渡，duration 代表0到1的用时。
        /// 如果当前值在0到1的中间则会相应缩短总时间
        /// </summary>
        public void NewEase_Weight(float newGoal) {
            beginValue = outputValue;
            goalValue = newGoal;
            timeAlpha = 0; // 也可以 SetAlpha(0)，但是要多算几步
            var dtValue = math.abs(goalValue - beginValue);
            remainingTime = dtValue * duration; // 因为duration代表0到1的用时。所以省略了 “除以1” 
            //time = remainingTime;
        }

        void SetAlpha(float a) {
            timeAlpha = math.clamp(a, 0, 1);
            var valueAlpha = AlphaFunction(timeAlpha); // valueAlpha：值进度百分比，0到1之间，下一步还原到起终值之间
            outputValue = beginValue + (goalValue - beginValue) * valueAlpha;
        }

        float AlphaFunction(float inAlpha) {
            return easeFunctionType switch {
                EaseFunctionType.Linear => EaseFunctions.Linear(inAlpha),
                EaseFunctionType.InSine => EaseFunctions.InSine(inAlpha),
                EaseFunctionType.OutSine => EaseFunctions.OutSine(inAlpha),
                EaseFunctionType.InOutSine => EaseFunctions.InOutSine(inAlpha),
                _ => throw new System.NotImplementedException($"undefine EaseFunctionType: {easeFunctionType}"),
            };
        }
    }
}
